package cg.cmm.alioss.utils;

import cg.cmm.alioss.config.OssConfig;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.time.Duration;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: baibing
 * create time: 2024-12-01 22:34
 * description:
 */
@Slf4j
@Component
public class AliyunOSSUtils {

    private final OssConfig ossConfig;

    public AliyunOSSUtils(OssConfig ossConfig) {
        this.ossConfig = ossConfig;
    }

    private OSS createOSSClient() {
        return new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
    }

    private void closeOSSClient(OSS ossClient) {
        if (ossClient != null) {
            ossClient.shutdown();
        }
    }

    public PutObjectResult uploadFile(MultipartFile file, String bucketName, String objectName) {
        try (InputStream inputStream = file.getInputStream()) {
            log.info("---------------- START UPLOAD FILE ----------------");
            log.info("Uploading to bucket '" + bucketName + "' with object name: " + objectName);
            OSS ossClient = createOSSClient();
            try {
                PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);
                log.info("===================== Upload File - Done! =====================");
                return putObjectResult;
            } finally {
                closeOSSClient(ossClient);
            }
        } catch (Exception e) {
            log.error("uploadFile Exception e:", e);
            return null;
        }
    }

    public PutObjectResult uploadFile(File file, String bucketName, String objectName) {
        try (InputStream inputStream = Files.newInputStream(file.toPath())) {
            log.info("---------------- START UPLOAD FILE ----------------");
            log.info("Uploading to bucket '" + bucketName + "' with object name: " + objectName);
            OSS ossClient = createOSSClient();
            try {
                PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);
                log.info("===================== Upload File - Done! =====================");
                return putObjectResult;
            } finally {
                closeOSSClient(ossClient);
            }
        } catch (Exception e) {
            log.error("uploadFile Exception e:", e);
            return null;
        }
    }

    public PutObjectResult uploadFile(InputStream inputStream, String bucketName, String objectName) {
        try {
            log.info("---------------- START UPLOAD FILE ----------------");
            log.info("Uploading to bucket '" + bucketName + "' with object name: " + objectName);
            OSS ossClient = createOSSClient();
            try {
                PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);
                log.info("===================== Upload File - Done! =====================");
                return putObjectResult;
            } finally {
                closeOSSClient(ossClient);
            }
        } catch (Exception e) {
            log.error("uploadFile Exception e:", e);
            return null;
        }
    }

    public OSSObject downloadFile(String bucketName, String objectName) {
        try {
            log.info("---------------- START DOWNLOAD FILE ----------------");
            log.info("Downloading from bucket '" + bucketName + "' with object name: " + objectName);
            OSS ossClient = createOSSClient();
            try {
                OSSObject ossObject = ossClient.getObject(bucketName, objectName);
                log.info("===================== Download File - Done! =====================");
                return ossObject;
            } finally {
                closeOSSClient(ossClient);
            }
        } catch (Exception e) {
            log.error("downloadFile Exception e:", e);
            return null;
        }
    }

    public boolean isExist(String bucketName, String objectName) {
        try {
            log.info("---------------- START CHECK FILE EXIST ----------------");
            log.info("CHECK FILE EXIST in bucket '" + bucketName + "' with object name: " + objectName);
            OSS ossClient = createOSSClient();
            try {
                boolean exists = ossClient.doesObjectExist(bucketName, objectName);
                log.info("===================== CHECK FILE EXIST - Done! =====================");
                return exists;
            } finally {
                closeOSSClient(ossClient);
            }
        } catch (Exception e) {
            log.error("CHECK FILE EXIST Exception e:", e);
            return false;
        }
    }

    public String getPreSignedUrl(String bucketName, String objectName, Duration duration, Integer flag, String fileName) {
        if (StringUtils.isEmpty(bucketName) || StringUtils.isEmpty(objectName)) {
            log.error("param null");
            return null;
        }
        try {
            Date expiration = new Date(System.currentTimeMillis() + duration.toMillis());
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName);
            request.setExpiration(expiration);

            // 设置Content-Type
            if (flag == -1) {
                request.setContentType(getContentType(objectName));
            } else {
                request.setContentType("binary/octet-stream");
            }

            OSS ossClient = createOSSClient();
            try {
                URL url = ossClient.generatePresignedUrl(request);
                return url.toString();
            } finally {
                closeOSSClient(ossClient);
            }
        } catch (Exception e) {
            log.error("getPreSignedUrl Exception e:", e);
            return null;
        }
    }

    private String getContentType(String objectName) {
        String extension = objectName.substring(objectName.lastIndexOf('.') + 1).toLowerCase();
        switch (extension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "pdf":
                return "application/pdf";
            case "doc":
                return "application/msword";
            // 添加更多文件类型...
            default:
                return "binary/octet-stream";
        }
    }

    public List<String> listObjects(String bucketName, String prefix) {
        OSS ossClient = createOSSClient();
        try {
            ObjectListing objectListing = ossClient.listObjects(bucketName, prefix);
            List<OSSObjectSummary> objectSummaries = objectListing.getObjectSummaries();
            return objectSummaries.stream()
                    .sorted(Comparator.comparing(OSSObjectSummary::getSize))
                    .map(OSSObjectSummary::getKey)
                    .collect(Collectors.toList());
        } finally {
            closeOSSClient(ossClient);
        }
    }
}
